#include <jni.h>
#include <string>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "mdcif.h"
#include "log.h"
#include "datatype.h"
#include "log.h"
//#include "native-lib.h"
#include <android/log.h>
#include <unistd.h>

#define  LOG_TAG "mhd_aecm"

#define  LOGE(...)   __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

//全局变量  解决子线程访问问题
jobject global_obj = NULL;
jclass global_class = NULL;
jclass global_oilGun_class = NULL;
//java虚拟机
JavaVM *jvm = NULL;

static void checkException(JNIEnv *env);

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    jvm = vm;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    jclass fccUtils = env->FindClass("com/czb/wisdomcashier/utils/FccUtils");
    jclass fccOilGunBean = env->FindClass("com/czb/wisdomcashier/FccOilGunBean");
    global_oilGun_class = (jclass) env->NewGlobalRef(fccOilGunBean);
    jmethodID instance = env->GetStaticMethodID(fccUtils, "getInstance",
                                                "()Lcom/czb/wisdomcashier/utils/FccUtils;");
    jobject thiz = env->CallStaticObjectMethod(fccUtils, instance);
    global_class = (jclass) env->NewGlobalRef(fccUtils);
    global_obj = (jobject) env->NewGlobalRef(thiz);

    char *systemTime = (char *) malloc(sizeof(char) * 10);
    sprintf(systemTime, "mdcNo = %d", 4);
    LogOut(systemTime);

    return JNI_VERSION_1_6;
}


jstring charToJstring(JNIEnv *env, char *pat) {
    jclass strClass = (env)->FindClass("java/lang/String");
    jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    jbyteArray bytes = (env)->NewByteArray(strlen(pat));
    (env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *) pat);
    jstring encoding = (env)->NewStringUTF("utf-8");
    return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}


void correctUtfBytes(char *bytes) {
    char three = 0;
    while (*bytes != '\0') {
        unsigned char utf8 = *(bytes++);
        three = 0;
        // Switch on the high four bits.
        switch (utf8 >> 4) {
            case 0x00:
            case 0x01:
            case 0x02:
            case 0x03:
            case 0x04:
            case 0x05:
            case 0x06:
            case 0x07:
                // Bit pattern 0xxx. No need for any extra bytes.
                break;
            case 0x08:
            case 0x09:
            case 0x0a:
            case 0x0b:
            case 0x0f:
                /*
                 * Bit pattern 10xx or 1111, which are illegal start bytes.
                 * Note: 1111 is valid for normal UTF-8, but not the
                 * modified UTF-8 used here.
                 */
                *(bytes - 1) = '?';
                break;
            case 0x0e:
                // Bit pattern 1110, so there are two additional bytes.
                utf8 = *(bytes++);
                if ((utf8 & 0xc0) != 0x80) {
                    --bytes;
                    *(bytes - 1) = '?';
                    break;
                }
                three = 1;
                // Fall through to take care of the final byte.
            case 0x0c:
            case 0x0d:
                // Bit pattern 110x, so there is one additional byte.
                utf8 = *(bytes++);
                if ((utf8 & 0xc0) != 0x80) {
                    --bytes;
                    if (three)--bytes;
                    *(bytes - 1) = '?';
                }
                break;
        }
    }
}


jstring charTojstring(JNIEnv *env, const char *pat) {
    //定义java String类 strClass
    jclass strClass = (env)->FindClass("java/lang/String");
    //获取String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
    jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    //建立byte数组
    jbyteArray bytes = (env)->NewByteArray(strlen(pat));
    //将char* 转换为byte数组
    (env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *) pat);
    // 设置String, 保存语言类型,用于byte数组转换至String时的参数
    jstring encoding = (env)->NewStringUTF("GB2312");
    //将byte数组转换为java String,并输出
    return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}

char *jstringToChar(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("GB2312");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}

//错误回调
void OnErrorEvent(int mdcNo, char *pzErrInfo) {
    LOGE("=====================OnErrorEvent = %d", 1);
    LogOut(pzErrInfo);
    JNIEnv *jniEvn = __null;
    if (jvm->GetEnv((void **) &jniEvn, JNI_VERSION_1_6) == JNI_OK) {
        jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "log", "(Ljava/lang/String;)V");
        jstring time = (jstring) jniEvn->NewStringUTF(pzErrInfo);
        jniEvn->CallVoidMethod(global_obj, voidMethodId, time);
    } else {
        JavaVMAttachArgs args = {JNI_VERSION_1_6, __FUNCTION__, __null};
        jvm->AttachCurrentThread(&jniEvn, &args);
        jstring time = (jstring) jniEvn->NewStringUTF(pzErrInfo);
        jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "log", "(Ljava/lang/String;)V");
        jniEvn->CallVoidMethod(global_obj, voidMethodId, time);
        jvm->DetachCurrentThread();
    }
    char *systemTime = (char *) malloc(sizeof(char) * 10);
    sprintf(systemTime, "mdcNo = %d", mdcNo);
    LogOut(systemTime);
}

//事件回调函数实现部分   回调有的在子线程，有的在主线程中
void OnNotifyEvent(int mdcNo, int EvtId, BYTE *pBuf, uint32 uSize) {

    const uint32 UMAX = 512;
    if (uSize > UMAX) {
        LogOut("Error: ");
        return;
    }

    BYTE Buffer[UMAX] = {0};
    BYTE *pData = Buffer;
    memcpy(Buffer, pBuf, uSize);

    mdcNo;//注册时注册的编号是几，这里就是是几，比如是1，这里就会是1；
    LOGE("MDC OnNotifyEvent   EvtId    #%d ", EvtId);
    switch (EvtId) {
        case 101: //MDC状态回调，pData:指向MDCSTATUS类弄数据，uSize: 4, 其值为Offline或Online表法断开或连接，状态变更时通知一次，当MDC断开时，其上所有通道连接设备均为断开，此时枪状不上传；
        {
            int sta = *((int *) pData);
            if (sta == 1) {
                LOGE("MDC #%d conected.", mdcNo);
            } else {
                LOGE("MDC #%d distincted.", mdcNo);
            }
            JNIEnv *jniEvn = __null;
            if (jvm->GetEnv((void **) &jniEvn, JNI_VERSION_1_6) == JNI_OK) {
                checkException(jniEvn);
                jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "connection", "(IZ)V");
                jniEvn->CallVoidMethod(global_obj, voidMethodId, mdcNo, sta);
            } else {
                JavaVMAttachArgs args = {JNI_VERSION_1_6, __FUNCTION__, __null};
                jvm->AttachCurrentThread(&jniEvn, &args);
                jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "connection", "(IZ)V");
                jniEvn->CallVoidMethod(global_obj, voidMethodId, mdcNo, sta);
                jvm->DetachCurrentThread();
            }
        }
            break;

        case 102: //枪状态通知回调，pData指向一个TNZLSTATUS结构体，uSize为的TNZLSTATUS结构大小，当枪状态发生变更时会实时上报，加油中大约一秒回调3-5次，当状态未发生改变时，约1分钟回调一次；
        {
            TNZLSTATUS st = *((TNZLSTATUS *) pData);
            LOGE("枪状态通知回调    EvtId:%d, ChlNo:%d, NZL:%d, Status:%d, VOL:%d, Money:%d", EvtId,
                 st.ChlNo, st.NZL, st.Status, st.VOL, st.Money);

            //获取Java实例
            JNIEnv *jniEvn = __null;
            int status;
            bool isAttached = false;
            JavaVMAttachArgs args = {JNI_VERSION_1_6, __FUNCTION__, __null};
            status = jvm->GetEnv((void **) &jniEvn, JNI_VERSION_1_6);
            if (status < 0) {
                if (jvm->AttachCurrentThread(&jniEvn, &args)) {
                    return;
                }
                isAttached = true;
            }

            jmethodID voidMethodId = jniEvn->GetMethodID(global_class,
                                                         "call", "(Ljava/lang/Object;)V");
            //获取成员变量
            jmethodID objectClassInitID = (jniEvn)->GetMethodID(global_oilGun_class, "<init>",
                                                                "()V");
            jobject objectNewEng = (jniEvn)->NewObject(global_oilGun_class, objectClassInitID);

            jfieldID chlNoId = (jniEvn)->GetFieldID(global_oilGun_class, "ChlNo", "I");
            (jniEvn)->SetIntField(objectNewEng, chlNoId, st.ChlNo);
            jfieldID nzl = (jniEvn)->GetFieldID(global_oilGun_class, "NZL", "I");
            (jniEvn)->SetIntField(objectNewEng, nzl, st.NZL);
//            (jniEvn)->SetIntField(objectNewEng, nzl, 11);
            jfieldID statusId = (jniEvn)->GetFieldID(global_oilGun_class, "status", "I");
            (jniEvn)->SetIntField(objectNewEng, statusId, st.Status);
            jfieldID volId = (jniEvn)->GetFieldID(global_oilGun_class, "VOL", "I");
            (jniEvn)->SetIntField(objectNewEng, volId, st.VOL);
            jfieldID moneyId = (jniEvn)->GetFieldID(global_oilGun_class, "Money", "I");
            (jniEvn)->SetIntField(objectNewEng, moneyId, st.Money);

            jfieldID evtId = (jniEvn)->GetFieldID(global_oilGun_class, "EvtId", "I");
            (jniEvn)->SetIntField(objectNewEng, evtId, EvtId);

            jniEvn->CallVoidMethod(global_obj, voidMethodId, objectNewEng);
            jniEvn->DeleteLocalRef(objectNewEng);
            if (isAttached) {
                jvm->DetachCurrentThread();
            }
        }
            break;

        case 103://上传交易，pData指向TRANSACTON的结构，uSize为TRANSACTON的结构大小，当有新加交产生时，自动通知一次，如果当时断线或通讯失败，则需要APP主动回叫，回叫后上传的交易，仍以此命令回复；
        {
            TRANSACTON rc = *((TRANSACTON *) pData);
            char *fmt = "枪状态通知回调    EvtId:%d, ChlNo:%d, NZL:%d, VOL:%d, Money:%d, Type:%d, CardNo:%s";
            LOGE(fmt, EvtId, rc.ChlNo, rc.NZL, rc.VOL, rc.Money, rc.CardType, rc.CardNo);

            //获取Java实例
            JNIEnv *jniEvn = __null;
            int status;
            bool isAttached = false;
            JavaVMAttachArgs args = {JNI_VERSION_1_6, __FUNCTION__, __null};
            status = jvm->GetEnv((void **) &jniEvn, JNI_VERSION_1_6);
            if (status < 0) {
                if (jvm->AttachCurrentThread(&jniEvn, &args)) {
                    return;
                }
                isAttached = true;
            }

            //获取成员变量
            jmethodID objectClassInitID = (jniEvn)->GetMethodID(global_oilGun_class, "<init>",
                                                                "()V");
            jobject objectNewEng = (jniEvn)->NewObject(global_oilGun_class, objectClassInitID);
            jfieldID chlNoId = (jniEvn)->GetFieldID(global_oilGun_class, "ChlNo", "I");
            (jniEvn)->SetIntField(objectNewEng, chlNoId, rc.ChlNo);
            jfieldID nzlId = (jniEvn)->GetFieldID(global_oilGun_class, "NZL", "I");
            (jniEvn)->SetIntField(objectNewEng, nzlId, rc.NZL);
//            (jniEvn)->SetIntField(objectNewEng, nzlId, 11);
            jfieldID oilCodeId = (jniEvn)->GetFieldID(global_oilGun_class, "OilCode", "I");
            (jniEvn)->SetIntField(objectNewEng, oilCodeId, rc.OilCode);
            jfieldID priceId = (jniEvn)->GetFieldID(global_oilGun_class, "Price", "I");
            (jniEvn)->SetIntField(objectNewEng, priceId, rc.Price);
            jfieldID volId = (jniEvn)->GetFieldID(global_oilGun_class, "VOL", "I");
            (jniEvn)->SetIntField(objectNewEng, volId, rc.VOL);
            jfieldID moneyId = (jniEvn)->GetFieldID(global_oilGun_class, "Money", "I");
            (jniEvn)->SetIntField(objectNewEng, moneyId, rc.Money);
            jfieldID yearId = (jniEvn)->GetFieldID(global_oilGun_class, "Year", "I");
            (jniEvn)->SetIntField(objectNewEng, yearId, rc.Year);
            jfieldID monthId = (jniEvn)->GetFieldID(global_oilGun_class, "Month", "I");
            (jniEvn)->SetIntField(objectNewEng, monthId, rc.Month);
            jfieldID dayId = (jniEvn)->GetFieldID(global_oilGun_class, "Day", "I");
            (jniEvn)->SetIntField(objectNewEng, dayId, rc.Day);
            jfieldID hourId = (jniEvn)->GetFieldID(global_oilGun_class, "Hour", "I");
            (jniEvn)->SetIntField(objectNewEng, hourId, rc.Hour);
            jfieldID minId = (jniEvn)->GetFieldID(global_oilGun_class, "Min", "I");
            (jniEvn)->SetIntField(objectNewEng, minId, rc.Min);
            jfieldID secId = (jniEvn)->GetFieldID(global_oilGun_class, "Sec", "I");
            (jniEvn)->SetIntField(objectNewEng, secId, rc.Sec);
            jfieldID vototId0 = (jniEvn)->GetFieldID(global_oilGun_class, "VTOT0", "I");
            (jniEvn)->SetIntField(objectNewEng, vototId0, (int) rc.VTOT0);
            jfieldID vototId1 = (jniEvn)->GetFieldID(global_oilGun_class, "VTOT1", "I");
            (jniEvn)->SetIntField(objectNewEng, vototId1, (int) rc.VTOT1);
            jfieldID pumptct = (jniEvn)->GetFieldID(global_oilGun_class, "PumpTTC", "I");
            (jniEvn)->SetIntField(objectNewEng, pumptct, (int) rc.PumpTTC);
            jfieldID evtId = (jniEvn)->GetFieldID(global_oilGun_class, "EvtId", "I");
            (jniEvn)->SetIntField(objectNewEng, evtId, EvtId);
            LOGE("上传交易  EvtId:%d, Year:%d, Month:%d, Day:%d, Hour: %d, Min:%d, Sec:%d MDCTTC:%d PumpTTC:%d ",
                 EvtId, rc.Year, rc.Month, rc.Day, rc.Hour, rc.Min, rc.Sec, rc.MDCTTC,
                 rc.PumpTTC);
            jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "call",
                                                         "(Ljava/lang/Object;)V");
            jniEvn->CallVoidMethod(global_obj, voidMethodId, objectNewEng);
            jniEvn->DeleteLocalRef(objectNewEng);
            if (isAttached) {
                jvm->DetachCurrentThread();
            }
        }
            break;
        case 104://上传MDC时间，当APP查询MDC时间时，回复此命令，如果时间与APP所在系统时间有差异时，APP可下发新的日期时间给MDC，以修正交易产生时间，pData为指向TDATETIME的结构，uSize为其长度；
        {
            TDATETIME rc = *((TDATETIME *) pData);

            //获取Java实例
            JNIEnv *jniEvn = __null;
            int status;
            bool isAttached = false;
            JavaVMAttachArgs args = {JNI_VERSION_1_6, __FUNCTION__, __null};
            status = jvm->GetEnv((void **) &jniEvn, JNI_VERSION_1_6);
            if (status < 0) {
                if (jvm->AttachCurrentThread(&jniEvn, &args)) {
                    return;
                }
                isAttached = true;
            }

            jvm->AttachCurrentThread(&jniEvn, &args);
            jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "systemTime",
                                                         "(ILjava/lang/String;)V");

            char *systemTime = (char *) malloc(sizeof(char) * 19);
            sprintf(systemTime, "%d-%d-%d %d:%d:%d", rc.Year, rc.Month, rc.Day, rc.Hour, rc.Min,
                    rc.Sec);
            jstring time = (jstring) jniEvn->NewStringUTF(systemTime);
            jniEvn->CallVoidMethod(global_obj, voidMethodId, mdcNo, time);

            if (isAttached) {
                jvm->DetachCurrentThread();
            }

            LOGE("MDC时间     rc.Year :%d", rc.Year);
            LOGE("MDC时间     rc.Month:%d", rc.Month);
            LOGE("MDC时间     rc.Day  :%d", rc.Day);
            LOGE("MDC时间     rc.Hour :%d", rc.Hour);
            LOGE("MDC时间     rc.Min  :%d", rc.Min);
            LOGE("MDC时间     rc.Sec  :%d", rc.Sec);
        }
            break;
        case 105: //上传枪油品信息，APP查询时回复，pData指向TNZLOILINFO的结构，uSize为其长度；
        {
            TNZLOILINFO rc = *((TNZLOILINFO *) pData);
            LOGE("枪油品信息  EvtId:%d, ChlNo:%d, NZL:%d, Price: %d, OilCode:%d, Density:%d ",
                 EvtId, rc.ChlNo, rc.NZL, rc.Price, rc.OilCode, rc.Density);
        }
            break;

        case 106: //上传枪实时泵码，APP查询时回复，pData指向TNZLVTOT的结构，uSize为其长度；
        {
            TNZLVTOT vt = *((TNZLVTOT *) pData);
            LOGE("EvtId:%d,  ChlNo:%d, NZL:%d, VTOT:%u", EvtId, vt.ChlNo, vt.NZL, vt.VTOT);
        }
            break;

        case 107: //上传发送给MDC的协议通讯数据，当成功向MDC发送数据后向上层反馈，pData为数据指针，uSize为其长度；
        {
            LogOut("Send:", pData, uSize);
            /*char *cha = (char *) pData;
            LOGE("LogOut%s    107   ", cha);
            LogOut(cha);
            JNIEnv *jniEvn = __null;
            JavaVMAttachArgs args = {JNI_VERSION_1_6, __FUNCTION__, __null};
            jvm->AttachCurrentThread(&jniEvn, &args);
            correctUtfBytes(cha);
            jstring time = charToJstring(jniEvn, cha);
            jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "log",
                                                         "(Ljava/lang/String;)V");
            jniEvn->CallVoidMethod(global_obj, voidMethodId, time);
            jvm->DetachCurrentThread();*/
        }
            break;
        case 108: //上传从MDC收到的协议通讯数据，当成功收到MDC发送数据后向上层反馈，pData为数据指针，uSize为其长度
            // ；107、108主要用于记录日志，以便系统查错或与油机间出现错误或故障时核查原因；
        {
            LogOut("Recv:", pData, uSize);
            /* char *cha = (char *) pData;
             LOGE("LogOut%s    108   ", cha);
             JNIEnv *jniEvn = __null;
             JavaVMAttachArgs args = {JNI_VERSION_1_6, __FUNCTION__, __null};
             jvm->AttachCurrentThread(&jniEvn, &args);
             correctUtfBytes(cha);
             jstring time = charToJstring(jniEvn, cha);
             jmethodID voidMethodId = jniEvn->GetMethodID(global_class, "log",
                                                          "(Ljava/lang/String;)V");
             jniEvn->CallVoidMethod(global_obj, voidMethodId, time);
             jvm->DetachCurrentThread();*/
        }
            break;
        case 109: //通知回叫的交易不存在，pData为指向TMDCTTC的结构，uSize为其长度
        {
            TMDCTTC rc = *((TMDCTTC *) pData);
//            ttc.ChlNo = chlNo;
//            ttc.TTC = ttcNo;//序列
            LOGE("109    TCC   ChlNo  =  %d      ttcNo  =  %d", rc.ChlNo, rc.TTC);
        }
            break;
        case 110: //110: 上传通道最大MDC TTC  TMDCTTC;
        {
            TMDCTTC rc = *((TMDCTTC *) pData);
            LOGE("   110   上传通道最大MDC    EvtId:%d, ChlNo:%d,  MAX MDCTTC: %d", EvtId, rc.ChlNo, rc.TTC);
        }
            break;
        case 111: //111: 获取授权时段的回调，Items 容量为3，
        {
            TAUTHCFG rc = *((TAUTHCFG *) pData);
            LOGE("   111   授权时段   ChlNo=%d   1  %d:%d:%d  ~  %d:%d:%d", rc.Num, rc.Items[0].tm0.Hour, rc.Items[0].tm0.Min, rc.Items[0].tm0.Sec,
                 rc.Items[0].tm1.Hour, rc.Items[0].tm1.Min, rc.Items[0].tm1.Sec);
            LOGE("   111   授权时段   ChlNo=%d   2  %d:%d:%d  ~  %d:%d:%d", rc.Num, rc.Items[1].tm0.Hour, rc.Items[1].tm0.Min, rc.Items[1].tm0.Sec,
                 rc.Items[1].tm1.Hour, rc.Items[1].tm1.Min, rc.Items[1].tm1.Sec);
            LOGE("   111   授权时段   ChlNo=%d   3  %d:%d:%d  ~  %d:%d:%d", rc.Num, rc.Items[2].tm0.Hour, rc.Items[2].tm0.Min, rc.Items[2].tm0.Sec,
                 rc.Items[2].tm1.Hour, rc.Items[2].tm1.Min, rc.Items[2].tm1.Sec);
        }
            break;
        case 112: //112: 当油枪在不可自由使用时段，提枪会申请授权，此回调场景是 提枪触发 -> 客户端收到授权申请
        {
            TNZLADDR rc = *((TNZLADDR *) pData);
            LOGE("   112   客户端收到授权申请   ChlNo=%d    NZL=%d", rc.ChlNo, rc.NZL);
        }
            break;
        case 113: //113: 授权的回调
        {
            TAUTHRESULT rc = *((TAUTHRESULT *) pData);
            LOGE("   113   授权   ChlNo=%d   NZL=%d   Result=%d", rc.ChlNo, rc.NZL, rc.Result);
        }
            break;
        case 114: //114: 取消授权的回调
        {
            TAUTHRESULT rc = *((TAUTHRESULT *) pData);
            LOGE("   114   取消授权   ChlNo=%d   NZL=%d   Result=%d", rc.ChlNo, rc.NZL, rc.Result);
        }
            break;
        case 115: //115: 获取集线器mac等硬件识别码 还没有生效
        {
            TDEVINFO rc = *((TDEVINFO *) pData);
            LOGE("   115   上传集线器硬件信息   SN=%s    MDate=%s", rc.SN, rc.MDate);
        }
            break;
    }
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_regErrorCallback(JNIEnv *env, jobject thiz) {
    int n = RegErrCallback(1, OnErrorEvent);
    return (jint) n;
}


//结束时处理
void Uinitialize(int mdcNo) {
    StopWork(mdcNo);
    UnregMDC(mdcNo);
}

//开始时可以这样调用
int Initialize(int mdcNo, char *ip, int port) {
    LOGE("TCC   mdcNo= %d", mdcNo);
    Uinitialize(mdcNo);
    int reg = RegMDC(mdcNo);
    int x = RegNotifyEventCallback(mdcNo, OnNotifyEvent);    //look log file!!!
    int z = RegErrCallback(mdcNo, OnErrorEvent);    //look log file!!!
    int init = MDCInit(mdcNo, ip, port);
    int work = StartWork(mdcNo);
    LOGE("TCC   StartWork= %d", work);
    return work;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_initAll(JNIEnv *env, jobject thiz, jint mdcNo, jstring ip, jint port) {
    int status = Initialize(mdcNo, jstringToChar(env, ip), port);
    return (jint) status;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_RegNotifyEventCallback(JNIEnv *env, jobject thiz, jint mdcNo) {
    return RegNotifyEventCallback(mdcNo, OnNotifyEvent);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_UnregMDC(JNIEnv *env, jobject thiz, jint mdcNo) {
    return UnregMDC(mdcNo);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_RegErrCallback(JNIEnv *env, jobject thiz, jint mdcNo) {
    int reg = RegErrCallback(mdcNo, OnErrorEvent);
    LOGE("mdc   RegErrCallback=%d", reg);
    return reg;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_MDCInit(JNIEnv *env, jobject thiz, jint mdcNo, jstring ip, jint port) {
    int reg = MDCInit(mdcNo, jstringToChar(env, ip), port);
    LOGE("mdc   MDCInit=%d", reg);
    return MDCInit(mdcNo, jstringToChar(env, ip), port);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_RegMDC(JNIEnv *env, jobject thiz, jint mdcNo) {
    int reg = RegMDC(mdcNo);
    LOGE("mdc   RegMDC=%d", reg);
    return RegMDC(mdcNo);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_QryTTC(JNIEnv *env, jobject thiz, jint mdcNo, jint chlNo, jint ttcNo) {
    TMDCTTC ttc;
    ttc.ChlNo = chlNo;
    ttc.TTC = ttcNo;//序列
    LOGE("TCC   ChlNo  =  %d      ttcNo  =  %d", chlNo, ttcNo);
    int n = DoCommand(mdcNo, 206, (BYTE *) (&ttc), sizeof(ttc));
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_QryVTOT(JNIEnv *env, jobject thiz, jint mdcNo, jint chlno, jint nzl) {
    LOGE("MDC  查询枪泵码    205   chlno  =  %d      nzl  =  %d", chlno, nzl);
    TNZLADDR adr;
    adr.ChlNo = chlno;
    adr.NZL = nzl;
    int n = DoCommand(mdcNo, 205, (BYTE *) (&adr), sizeof(adr));
    return (jint) n;
}


extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_SetMDCTime(JNIEnv *env, jobject thiz, jint mdcNo,
                                                     jint year, jint month, jint day,
                                                     jint hour, jint min, jint sec) {
    LOGE("MDC  设置系统时间    202");
    TDATETIME adr;
    adr.Year = year;
    adr.Month = month;
    adr.Day = day;
    adr.Hour = hour;
    adr.Min = min;
    adr.Sec = sec;
    int n = DoCommand(mdcNo, 202, (BYTE *) (&adr), sizeof(adr));
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_QryMDCTime(JNIEnv *env, jobject thiz, jint mdcNo) {
    LOGE("MDC  查询系统时间    201");
    int n = DoCommand(mdcNo, 201, NULL, 0);
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_SetNZLOilInfo(JNIEnv *env, jobject thiz, jint mdcNo, jint chl_no,
                                                        jint nzl, jint oil_code, jint price, jint density) {
    LOGE(" MDC  MDC发送设置枪油品指令    204  ChlNo:%d, NZL:%d, price:%d, density%d", chl_no, nzl, price, density);
    TNZLOILINFO adr;
    adr.ChlNo = chl_no;
    adr.NZL = nzl;
    adr.OilCode = oil_code;
    adr.Price = price;
    adr.Density = density;
    int n = DoCommand(mdcNo, 204, (BYTE *) (&adr), sizeof(adr));
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_QryNZLOilInfo(JNIEnv *env, jobject thiz, jint mdcNo, jint chlNo, jint nzl) {
    LOGE("MDC  MDC发送查询枪油品指令    203");
    TNZLADDR adr;
    adr.ChlNo = chlNo;
    adr.NZL = nzl;
    int n = DoCommand(mdcNo, 203, (BYTE *) (&adr), sizeof(adr));
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_startWork(JNIEnv *env, jobject thiz, jint mdc_no) {
    int work = StartWork(mdc_no);
    return work;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_StopWork(JNIEnv *env, jobject thiz, jint mdc_no) {
    int work = StopWork(mdc_no);
    return work;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_stopWork(JNIEnv *env, jobject thiz, jint mdc_no) {
    StopWork(mdc_no);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_getMaxTTC(JNIEnv *env, jobject thiz, int mdcNo, jint chlNo, jint nzl) {
    LOGE("MDC  查MAX订单    207");
    TNZLADDR adr;
    adr.ChlNo = chlNo;
    adr.NZL = nzl;
    int n = DoCommand(mdcNo, 207, (BYTE *) (&adr), sizeof(adr));
    LOGE("MDC  查MAX订单    ---->  %d", n);
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_getAuthCfg(JNIEnv *env, jobject thiz, jint mdcNo, jint chlNo, jint nzl) {
    LOGE("MDC  查时段    209");
    TNZLADDR adr;
    adr.ChlNo = chlNo;
    adr.NZL = nzl;
    int n = DoCommand(mdcNo, 209, (BYTE *) (&adr), sizeof(adr));
    LOGE("MDC  查时段    ---->  %d", n);
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_gunAuth(JNIEnv *env, jobject thiz, jint mdcNo, jint chlNo, jint nzl) {
    LOGE("MDC  授权    210");
    TNZLADDR adr;
    adr.ChlNo = chlNo;
    adr.NZL = nzl;
    int n = DoCommand(mdcNo, 210, (BYTE *) (&adr), sizeof(adr));
    LOGE("MDC  授权    210 ---->  ChlNo = %d  NZL = %d", chlNo,nzl);
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_gunCancelAuth(JNIEnv *env, jobject thiz, jint mdcNo, jint chlNo, jint nzl) {
    LOGE("MDC  取消授权    211");
    TNZLADDR adr;
    adr.ChlNo = chlNo;
    adr.NZL = nzl;
    int n = DoCommand(mdcNo, 211, (BYTE *) (&adr), sizeof(adr));
    LOGE("MDC  取消授权    211 ---->  ChlNo = %d  NZL = %d", chlNo,nzl);
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_setAuthCfg__IIIIIII(JNIEnv *env, jobject thiz, int mdcNo,
                                                              jint hour1, jint min1, jint sec1,
                                                              jint hour2, jint min2, jint sec2) {
    LOGE("MDC  设置时段  1  208");
    TTIME ttime1;
    ttime1.Hour = hour1;
    ttime1.Min = min1;
    ttime1.Sec = sec1;

    TTIME ttime2;
    ttime2.Hour = hour2;
    ttime2.Min = min2;
    ttime2.Sec = sec2;

    TPICETIME tpicetime;
    tpicetime.tm0 = ttime1;
    tpicetime.tm1 = ttime2;

    TAUTHCFG time;
    time.Num = 1;
    time.Items[0] = tpicetime;

    int n = DoCommand(mdcNo, 208, (BYTE *) (&time), sizeof(time));
    LOGE("MDC  设置时段    ---->  %d", n);
    return (jint) n;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_setAuthCfg__IIIIIIIIIIIII(JNIEnv *env, jobject thiz, int mdcNo,
                                                                    jint hourstart1, jint minstart1,
                                                                    jint secstart1, jint hourend1,
                                                                    jint minend1, jint secend1,
                                                                    jint hourstart2, jint minstart2,
                                                                    jint secstart2, jint hourend2,
                                                                    jint minend2, jint secend2) {

}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_setAuthCfg__IIIIIIIIIIIIIIIIIII(JNIEnv *env, jobject thiz, int mdcNo,
                                                                          jint hourstart1,
                                                                          jint minstart1,
                                                                          jint secstart1,
                                                                          jint hourend1,
                                                                          jint minend1,
                                                                          jint secend1,
                                                                          jint hourstart2,
                                                                          jint minstart2,
                                                                          jint secstart2,
                                                                          jint hourend2,
                                                                          jint minend2,
                                                                          jint secend2,
                                                                          jint hourstart3,
                                                                          jint minstart3,
                                                                          jint secstart3,
                                                                          jint hourend3,
                                                                          jint minend3,
                                                                          jint secend3) {

}

void checkException(JNIEnv *env) {
    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
    }
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_Uinitialize(JNIEnv *env, jobject thiz, jint mdcNo) {
    Uinitialize(mdcNo);
    return 1;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_QryDevInfo(JNIEnv *env, jobject thiz, jint mdcNo) {
    int n = DoCommand(mdcNo, 212, NULL, 0);
    LOGE("MDC  查询设备SN    ---->  %d", n);
    return 1;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_czb_wisdomcashier_utils_FccUtils_reStart(JNIEnv *env, jobject thiz, jint mdc_no) {
    StopWork(mdc_no);
    StartWork(mdc_no);
}